﻿using System;
using System.IO;

namespace InputFileGeneratorTest
{

    /// <summary>
    /// Types of validated elemets.
    /// </summary>
    enum TypeElement { DOUBLE, INT , COMPLEX_INT };

    /// <summary>
    /// YES in case if lenght of line is strict
    /// </summary>
    enum StrictSize { YES, NO };

    /// <summary>
    /// Helper for matrix validation
    /// </summary>
    class MatrixHelper
    {

        private static string DEFAULT_SEPARATOR = " ";

        // Declare delegate -- defines required signature:
        private delegate bool IsCorrectElement(string str);

        private static bool isCorrectInt(string element)
        {
            try
            {
                int.Parse(element);
            }
            catch (Exception e)
            {
                Console.Out.WriteLine(e.ToString());

                return false;
            }

            return true;
        }

        private static bool isCorrectDouble(string element)
        {
            try
            {
                double.Parse(element);
            }
            catch (Exception e)
            {
                Console.Out.WriteLine(e.ToString());

                return false;
            }

            return true;
        }

        private static bool isCorrectComplexInt(string element)
        {
            bool returnval = false;
            try
            {
                string[] str = element.Split(' ');

                if (str.Length != 2)
                {
                    throw new Exception("The element is not complex.");
                }

                int.Parse(str[0]);
                int.Parse(str[1]);

                returnval = true;
            }
            catch (Exception e)
            {
                Console.Out.WriteLine(e.ToString());
            }

            return returnval;
        }

        public static bool IsMatrixCareful(StreamReader reader, int x, int y, TypeElement el)
        {
            return IsMatrixCareful(reader, x, y, el, DEFAULT_SEPARATOR);
        }

        public static bool IsMatrixCareful(StreamReader reader, int x, int y, TypeElement el, string separator)
        {
            return IsMatrixCareful(reader, x, y, el, DEFAULT_SEPARATOR, StrictSize.YES);
        }

        public static bool IsMatrixCareful(StreamReader reader, int x, int y, TypeElement el, string separator,StrictSize strict)
        {
            bool returnval = false;
            try
            {
                IsCorrectElement isCorrect = null;

                //choose the type of validated elements
                switch (el)
                {
                    case TypeElement.DOUBLE:
                        isCorrect = isCorrectDouble;
                        break;
                    case TypeElement.INT:
                        isCorrect = isCorrectInt;
                        break;
                    case TypeElement.COMPLEX_INT:
                        isCorrect = isCorrectComplexInt;
                        break;
                    default:
                        isCorrect = isCorrectDouble;
                        break;
                }

                for (int i = 0; i < y; i++)
                {
                    string[] strArray = reader.ReadLine().Split(separator.ToCharArray());
                    if (StrictSize.YES.Equals(strict) && strArray.Length != x)
                    {
                        throw new Exception("Incorrect matrix dimension.");
                    }
                    else if(StrictSize.NO.Equals(strict) && x < strArray.Length)
                    {
                        throw new Exception("Incorrect matrix dimension.");
                    }

                    foreach (string str in strArray)
                    {
                        if (!isCorrect(str))
                        {
                            throw new Exception("Incorrect element format.");                           
                        }
                    }
                }

                returnval = true;
            }
            catch (Exception e)
            {
                Console.Out.WriteLine(e.ToString());
            }

            return returnval;
        }
    }
}
